@rubytech/create-realagent 1.0.635 → 1.0.637
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +20 -0
- package/package.json +1 -1
- package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +1 -1
- package/payload/platform/plugins/memory/mcp/scripts/graph/accept.sh +96 -8
- package/payload/platform/plugins/memory/references/graph-primitives.md +4 -4
- package/payload/platform/scripts/setup.sh +1 -1
- package/payload/server/chunk-LM5BMENF.js +77 -0
- package/payload/server/index.js +7225 -0
- package/payload/server/public/assets/{admin-BTjragNx.js → admin-E3EIZIw0.js} +31 -31
- package/payload/server/public/index.html +1 -1
- package/payload/server/server.js +112 -71
- package/payload/server/upgrade-progress-server.js +83 -0
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const PAYLOAD_DIR = resolve(import.meta.dirname, "../payload");
|
|
|
8
8
|
// The bundler stamps brand.json into the payload at build time.
|
|
9
9
|
const BRAND_PATH = join(PAYLOAD_DIR, "platform", "config", "brand.json");
|
|
10
10
|
if (!existsSync(BRAND_PATH)) {
|
|
11
|
+
console.error("Setup failed: brand.json not found in payload (package may be corrupted)");
|
|
11
12
|
console.error("FATAL: brand.json not found in payload. Package may be corrupted.");
|
|
12
13
|
process.exit(1);
|
|
13
14
|
}
|
|
@@ -16,6 +17,7 @@ try {
|
|
|
16
17
|
BRAND = JSON.parse(readFileSync(BRAND_PATH, "utf-8"));
|
|
17
18
|
}
|
|
18
19
|
catch (err) {
|
|
20
|
+
console.error(`Setup failed: failed to parse brand.json: ${err.message}`);
|
|
19
21
|
console.error(`FATAL: Failed to parse brand.json: ${err.message}`);
|
|
20
22
|
process.exit(1);
|
|
21
23
|
}
|
|
@@ -1335,6 +1337,7 @@ function createTunnelSymlink(linkPath, target) {
|
|
|
1335
1337
|
catch (err) {
|
|
1336
1338
|
const code = err.code;
|
|
1337
1339
|
if (code !== "ENOENT") {
|
|
1340
|
+
console.error(`Setup failed: ${linkPath} lstat failed: ${err.message}`);
|
|
1338
1341
|
console.error(`[create-maxy:error] ${linkPath} lstat failed: ${err.message}`);
|
|
1339
1342
|
process.exit(1);
|
|
1340
1343
|
}
|
|
@@ -1346,6 +1349,7 @@ function createTunnelSymlink(linkPath, target) {
|
|
|
1346
1349
|
return;
|
|
1347
1350
|
}
|
|
1348
1351
|
if (!lstat.isSymbolicLink()) {
|
|
1352
|
+
console.error(`Setup failed: ${linkPath} collision (regular file)`);
|
|
1349
1353
|
console.error(`[create-maxy:collision] ${linkPath} already exists target=<regular-file>`);
|
|
1350
1354
|
console.error(` Remove the file and re-run: npx -y @rubytech/create-maxy`);
|
|
1351
1355
|
process.exit(1);
|
|
@@ -1356,6 +1360,7 @@ function createTunnelSymlink(linkPath, target) {
|
|
|
1356
1360
|
resolvedTarget = resolve(dirname(linkPath), raw);
|
|
1357
1361
|
}
|
|
1358
1362
|
catch (err) {
|
|
1363
|
+
console.error(`Setup failed: ${linkPath} symlink unreadable: ${err.message}`);
|
|
1359
1364
|
console.error(`[create-maxy:collision] ${linkPath} symlink unreadable: ${err.message}`);
|
|
1360
1365
|
console.error(` Remove the file and re-run: npx -y @rubytech/create-maxy`);
|
|
1361
1366
|
process.exit(1);
|
|
@@ -1386,6 +1391,7 @@ function createTunnelSymlink(linkPath, target) {
|
|
|
1386
1391
|
logFile(` symlink repaired (dangling): ${linkPath} was ${resolvedTarget}, now ${targetAbs}`);
|
|
1387
1392
|
return;
|
|
1388
1393
|
}
|
|
1394
|
+
console.error(`Setup failed: ${linkPath} collision (symlink to ${resolvedTarget})`);
|
|
1389
1395
|
console.error(`[create-maxy:collision] ${linkPath} already exists target=${resolvedTarget}`);
|
|
1390
1396
|
console.error(` This symlink was created by a different install (not within ${INSTALL_DIR}).`);
|
|
1391
1397
|
console.error(` Remove or relocate it, then re-run: npx -y @rubytech/create-maxy`);
|
|
@@ -1401,6 +1407,7 @@ function installTunnelScripts() {
|
|
|
1401
1407
|
chmodSync(src, 0o755);
|
|
1402
1408
|
}
|
|
1403
1409
|
catch (err) {
|
|
1410
|
+
console.error(`Setup failed: tunnel script missing or chmod failed: ${src}`);
|
|
1404
1411
|
console.error(`[create-maxy:error] tunnel script missing or chmod failed: ${src}`);
|
|
1405
1412
|
console.error(` ${err.message}`);
|
|
1406
1413
|
process.exit(1);
|
|
@@ -1684,6 +1691,7 @@ WantedBy=multi-user.target
|
|
|
1684
1691
|
vncLog = `(no boot log found at ${vncLogPath})`;
|
|
1685
1692
|
}
|
|
1686
1693
|
console.error("");
|
|
1694
|
+
console.error("Setup failed: Browser automation unavailable — CDP port 9222 not responding");
|
|
1687
1695
|
console.error(" ERROR: Browser automation unavailable — CDP port 9222 not responding.");
|
|
1688
1696
|
console.error(" Chromium should be started by vnc.sh (ExecStartPre). Check the boot log:");
|
|
1689
1697
|
console.error("");
|
|
@@ -1704,6 +1712,7 @@ WantedBy=multi-user.target
|
|
|
1704
1712
|
}
|
|
1705
1713
|
catch (err) {
|
|
1706
1714
|
console.error("");
|
|
1715
|
+
console.error(`Setup failed: tunnel script symlink missing or not executable: ${linkPath}`);
|
|
1707
1716
|
console.error(` [create-maxy:error] tunnel script symlink missing or not executable: ${linkPath}`);
|
|
1708
1717
|
console.error(` ${err.message}`);
|
|
1709
1718
|
process.exit(1);
|
|
@@ -1721,6 +1730,7 @@ if (_args.includes("--uninstall")) {
|
|
|
1721
1730
|
const exportPath = exportIdx !== -1 ? _args[exportIdx + 1] : undefined;
|
|
1722
1731
|
const skipConfirm = _args.includes("--yes");
|
|
1723
1732
|
if (exportIdx !== -1 && !exportPath) {
|
|
1733
|
+
console.error("Setup failed: --export-data requires a path argument");
|
|
1724
1734
|
console.error("--export-data requires a path argument.");
|
|
1725
1735
|
process.exit(1);
|
|
1726
1736
|
}
|
|
@@ -1741,6 +1751,7 @@ if (portIdx !== -1) {
|
|
|
1741
1751
|
const raw = _args[portIdx + 1];
|
|
1742
1752
|
const parsed = raw ? parseInt(raw, 10) : NaN;
|
|
1743
1753
|
if (isNaN(parsed) || parsed < 1024 || parsed > 65535) {
|
|
1754
|
+
console.error(`Setup failed: --port requires a numeric value between 1024 and 65535 (got: ${raw ?? "nothing"})`);
|
|
1744
1755
|
console.error(`Error: --port requires a numeric value between 1024 and 65535 (got: ${raw ?? "nothing"}).`);
|
|
1745
1756
|
process.exit(1);
|
|
1746
1757
|
}
|
|
@@ -1797,11 +1808,13 @@ const hostnameIdx = _args.indexOf("--hostname");
|
|
|
1797
1808
|
if (hostnameIdx !== -1) {
|
|
1798
1809
|
const raw = _args[hostnameIdx + 1];
|
|
1799
1810
|
if (!raw || raw.startsWith("--")) {
|
|
1811
|
+
console.error("Setup failed: --hostname requires a value");
|
|
1800
1812
|
console.error("Error: --hostname requires a value (e.g. --hostname muvin).");
|
|
1801
1813
|
process.exit(1);
|
|
1802
1814
|
}
|
|
1803
1815
|
// RFC 1123: lowercase alphanumeric + hyphens, max 63 chars, no leading/trailing hyphen
|
|
1804
1816
|
if (!/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/.test(raw)) {
|
|
1817
|
+
console.error(`Setup failed: --hostname value '${raw}' is invalid`);
|
|
1805
1818
|
console.error(`Error: --hostname value '${raw}' is invalid. Must be lowercase letters, digits, and hyphens only (max 63 chars, no leading/trailing hyphen).`);
|
|
1806
1819
|
process.exit(1);
|
|
1807
1820
|
}
|
|
@@ -1813,10 +1826,12 @@ const displayIdx = _args.indexOf("--display");
|
|
|
1813
1826
|
if (displayIdx !== -1) {
|
|
1814
1827
|
const raw = _args[displayIdx + 1];
|
|
1815
1828
|
if (!raw || raw.startsWith("--")) {
|
|
1829
|
+
console.error("Setup failed: --display requires a value");
|
|
1816
1830
|
console.error("Error: --display requires a value: native or virtual.");
|
|
1817
1831
|
process.exit(1);
|
|
1818
1832
|
}
|
|
1819
1833
|
if (raw !== "native" && raw !== "virtual") {
|
|
1834
|
+
console.error(`Setup failed: --display value '${raw}' is invalid`);
|
|
1820
1835
|
console.error(`Error: --display value '${raw}' is invalid. Must be 'native' or 'virtual'.`);
|
|
1821
1836
|
process.exit(1);
|
|
1822
1837
|
}
|
|
@@ -1864,12 +1879,14 @@ let EMBED_SOURCE = "default";
|
|
|
1864
1879
|
const embedModelIdx = _args.indexOf("--embed-model");
|
|
1865
1880
|
const embedDimsIdx = _args.indexOf("--embed-dimensions");
|
|
1866
1881
|
if (embedDimsIdx !== -1 && embedModelIdx === -1) {
|
|
1882
|
+
console.error("Setup failed: --embed-dimensions requires --embed-model");
|
|
1867
1883
|
console.error("Error: --embed-dimensions requires --embed-model (dimensions are model-specific).");
|
|
1868
1884
|
process.exit(1);
|
|
1869
1885
|
}
|
|
1870
1886
|
if (embedModelIdx !== -1) {
|
|
1871
1887
|
const raw = _args[embedModelIdx + 1];
|
|
1872
1888
|
if (!raw || raw.startsWith("--")) {
|
|
1889
|
+
console.error("Setup failed: --embed-model requires a value");
|
|
1873
1890
|
console.error("Error: --embed-model requires a value (e.g. --embed-model mxbai-embed-large).");
|
|
1874
1891
|
process.exit(1);
|
|
1875
1892
|
}
|
|
@@ -1880,6 +1897,7 @@ if (embedModelIdx !== -1) {
|
|
|
1880
1897
|
const rawDims = _args[embedDimsIdx + 1];
|
|
1881
1898
|
const parsed = rawDims ? parseInt(rawDims, 10) : NaN;
|
|
1882
1899
|
if (isNaN(parsed) || parsed <= 0) {
|
|
1900
|
+
console.error(`Setup failed: --embed-dimensions requires a positive integer (got: ${rawDims ?? "nothing"})`);
|
|
1883
1901
|
console.error(`Error: --embed-dimensions requires a positive integer (got: ${rawDims ?? "nothing"}).`);
|
|
1884
1902
|
process.exit(1);
|
|
1885
1903
|
}
|
|
@@ -1891,6 +1909,7 @@ if (embedModelIdx !== -1) {
|
|
|
1891
1909
|
}
|
|
1892
1910
|
else {
|
|
1893
1911
|
// Unknown model without explicit dimensions — cannot proceed
|
|
1912
|
+
console.error(`Setup failed: unknown embedding model '${EMBED_MODEL}'`);
|
|
1894
1913
|
console.error(`Error: Unknown embedding model '${EMBED_MODEL}'.`);
|
|
1895
1914
|
console.error("Known models and their dimensions:");
|
|
1896
1915
|
for (const [model, dims] of Object.entries(EMBED_MODEL_DIMS)) {
|
|
@@ -1943,6 +1962,7 @@ if (neo4jPortIdx !== -1) {
|
|
|
1943
1962
|
const raw = _args[neo4jPortIdx + 1];
|
|
1944
1963
|
const parsed = raw ? parseInt(raw, 10) : NaN;
|
|
1945
1964
|
if (isNaN(parsed) || parsed < 1024 || parsed > 65535) {
|
|
1965
|
+
console.error(`Setup failed: --neo4j-port requires a numeric value between 1024 and 65535 (got: ${raw ?? "nothing"})`);
|
|
1946
1966
|
console.error(`Error: --neo4j-port requires a numeric value between 1024 and 65535 (got: ${raw ?? "nothing"}).`);
|
|
1947
1967
|
process.exit(1);
|
|
1948
1968
|
}
|
package/package.json
CHANGED
|
@@ -280,7 +280,7 @@ if ! command -v dig >/dev/null 2>&1; then
|
|
|
280
280
|
phase_line setup-tunnel step=zone-preflight result=error \
|
|
281
281
|
reason=dig-missing
|
|
282
282
|
echo "ERROR: dig is not in PATH — required for the zone pre-flight check." >&2
|
|
283
|
-
echo "
|
|
283
|
+
echo " Re-run the Maxy installer to reprovision DNS tooling (bind9-dnsutils)." >&2
|
|
284
284
|
exit 1
|
|
285
285
|
fi
|
|
286
286
|
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
2
|
+
# Acceptance harness for the graph MCP integration.
|
|
3
3
|
#
|
|
4
4
|
# Spawns the graph shim, drives it as a JSON-RPC client over stdio, runs
|
|
5
5
|
# one query per acceptance class, prints PASS/FAIL per check, and exits
|
|
6
6
|
# non-zero if any check fails. Assumes the brand's Neo4j is running and
|
|
7
7
|
# the fixture in fixture.cypher has been seeded.
|
|
8
8
|
#
|
|
9
|
+
# The tools/list assertion guards against FastMCP-joiner drift: the
|
|
10
|
+
# upstream server joins NEO4J_NAMESPACE to each tool name with a hyphen,
|
|
11
|
+
# and the admin allowlist is string-exact. If a future upstream upgrade
|
|
12
|
+
# changes the joiner, the assertion fails with a named reason before any
|
|
13
|
+
# functional check runs.
|
|
14
|
+
#
|
|
9
15
|
# Usage:
|
|
10
16
|
# PLATFORM_ROOT=~/.maxy/platform bash accept.sh # infers NEO4J_URI from env
|
|
11
17
|
# PLATFORM_ROOT=~/.maxy/platform NEO4J_URI=bolt://localhost:7687 bash accept.sh
|
|
@@ -36,10 +42,88 @@ PASS=0
|
|
|
36
42
|
FAIL=0
|
|
37
43
|
TOTAL=0
|
|
38
44
|
|
|
45
|
+
# Exported env used by the inline Node clients below.
|
|
46
|
+
export SHIM
|
|
47
|
+
export PLATFORM_ROOT
|
|
48
|
+
|
|
49
|
+
# ---------------------------------------------------------------------------
|
|
50
|
+
# Regression guard: tools/list must register hyphen-joined names only.
|
|
51
|
+
#
|
|
52
|
+
# FastMCP joins NEO4J_NAMESPACE ("maxy-graph") to each upstream tool with a
|
|
53
|
+
# hyphen, producing `maxy-graph-read_neo4j_cypher` and
|
|
54
|
+
# `maxy-graph-get_neo4j_schema`. Claude Code's MCP client adds `mcp__graph__`
|
|
55
|
+
# on top when registering the server — the admin allowlist in
|
|
56
|
+
# platform/ui/app/lib/claude-agent.ts must match those exact names.
|
|
57
|
+
# A future upstream version that changes the joiner (e.g. to underscore)
|
|
58
|
+
# silently re-introduces a class of denial unless this fires.
|
|
59
|
+
# ---------------------------------------------------------------------------
|
|
60
|
+
assert_tools_list() {
|
|
61
|
+
TOTAL=$(( TOTAL + 1 ))
|
|
62
|
+
local out
|
|
63
|
+
if ! out=$(
|
|
64
|
+
node -e "
|
|
65
|
+
const { spawn } = require('node:child_process');
|
|
66
|
+
const proc = spawn('node', [process.env.SHIM], { stdio: ['pipe', 'pipe', 'inherit'] });
|
|
67
|
+
let buf = '';
|
|
68
|
+
proc.stdout.on('data', (chunk) => { buf += chunk.toString('utf8'); });
|
|
69
|
+
const send = (obj) => proc.stdin.write(JSON.stringify(obj) + '\n');
|
|
70
|
+
send({ jsonrpc: '2.0', id: 1, method: 'initialize',
|
|
71
|
+
params: { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'accept.sh', version: '1.0' } } });
|
|
72
|
+
setTimeout(() => {
|
|
73
|
+
send({ jsonrpc: '2.0', method: 'notifications/initialized' });
|
|
74
|
+
send({ jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} });
|
|
75
|
+
}, 1500);
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
proc.kill('SIGTERM');
|
|
78
|
+
const lines = buf.split('\n').filter(Boolean);
|
|
79
|
+
for (const line of lines) {
|
|
80
|
+
try { const m = JSON.parse(line); if (m.id === 2) {
|
|
81
|
+
if (m.error) { console.error('RPC_ERROR: ' + JSON.stringify(m.error)); process.exit(1); }
|
|
82
|
+
const names = (m.result && m.result.tools || []).map(t => t.name);
|
|
83
|
+
process.stdout.write(JSON.stringify(names));
|
|
84
|
+
process.exit(0);
|
|
85
|
+
} } catch (_) {}
|
|
86
|
+
}
|
|
87
|
+
console.error('NO_RESPONSE');
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}, 10000);
|
|
90
|
+
" 2>/dev/null
|
|
91
|
+
); then
|
|
92
|
+
echo "FAIL: tools/list RPC did not respond"
|
|
93
|
+
FAIL=$(( FAIL + 1 ))
|
|
94
|
+
return 1
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
local missing=""
|
|
98
|
+
for expected in "maxy-graph-read_neo4j_cypher" "maxy-graph-get_neo4j_schema"; do
|
|
99
|
+
if ! grep -q "\"$expected\"" <<<"$out"; then
|
|
100
|
+
missing+=" $expected"
|
|
101
|
+
fi
|
|
102
|
+
done
|
|
103
|
+
if [[ -n "$missing" ]]; then
|
|
104
|
+
echo "FAIL: tools/list missing hyphen-joined names —${missing} (reason: missing-hyphen-tool)"
|
|
105
|
+
echo " received: $out"
|
|
106
|
+
FAIL=$(( FAIL + 1 ))
|
|
107
|
+
return 1
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
if grep -qE 'maxy-graph_(read|get|write)' <<<"$out"; then
|
|
111
|
+
local stray
|
|
112
|
+
stray=$(grep -oE 'maxy-graph_[a-z_]+' <<<"$out" | sort -u | tr '\n' ' ')
|
|
113
|
+
echo "FAIL: tools/list contains underscore-joined variant(s) — ${stray}(reason: stray-underscore-tool)"
|
|
114
|
+
FAIL=$(( FAIL + 1 ))
|
|
115
|
+
return 1
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
echo "PASS: tools/list registers hyphen-joined names only (${#out}b response)"
|
|
119
|
+
PASS=$(( PASS + 1 ))
|
|
120
|
+
return 0
|
|
121
|
+
}
|
|
122
|
+
|
|
39
123
|
run_check() {
|
|
40
124
|
local label="$1"
|
|
41
125
|
local query="$2"
|
|
42
|
-
local tool="${3:-maxy-
|
|
126
|
+
local tool="${3:-maxy-graph-read_neo4j_cypher}"
|
|
43
127
|
TOTAL=$(( TOTAL + 1 ))
|
|
44
128
|
|
|
45
129
|
# Drive the shim via a short Node inline client. Exits 0 with the response
|
|
@@ -58,7 +142,7 @@ run_check() {
|
|
|
58
142
|
params: { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'accept.sh', version: '1.0' } } });
|
|
59
143
|
setTimeout(() => {
|
|
60
144
|
send({ jsonrpc: '2.0', method: 'notifications/initialized' });
|
|
61
|
-
const params = tool === 'maxy-
|
|
145
|
+
const params = tool === 'maxy-graph-get_neo4j_schema' ? {} : { query };
|
|
62
146
|
send({ jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: tool, arguments: params } });
|
|
63
147
|
}, 1500);
|
|
64
148
|
setTimeout(() => {
|
|
@@ -91,15 +175,19 @@ run_check() {
|
|
|
91
175
|
fi
|
|
92
176
|
}
|
|
93
177
|
|
|
94
|
-
#
|
|
95
|
-
|
|
96
|
-
|
|
178
|
+
# Run the regression guard first. If it fails, abort early — running
|
|
179
|
+
# functional queries with stale tool names produces misleading failures.
|
|
180
|
+
if ! assert_tools_list; then
|
|
181
|
+
echo ""
|
|
182
|
+
echo "FAIL — tool registration contract violated; aborting functional checks"
|
|
183
|
+
exit 1
|
|
184
|
+
fi
|
|
97
185
|
|
|
98
|
-
export TOOL="maxy-
|
|
186
|
+
export TOOL="maxy-graph-get_neo4j_schema"
|
|
99
187
|
export QUERY=""
|
|
100
188
|
run_check "get_neo4j_schema returns labels" ""
|
|
101
189
|
|
|
102
|
-
export TOOL="maxy-
|
|
190
|
+
export TOOL="maxy-graph-read_neo4j_cypher"
|
|
103
191
|
|
|
104
192
|
export QUERY="MATCH (n) RETURN labels(n)[0] AS type, count(*) AS n ORDER BY n DESC LIMIT 20"
|
|
105
193
|
run_check "enumerate by label" "$QUERY"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!-- Injected into admin system prompt by claude-agent.ts when agentType === "admin". -->
|
|
2
|
-
<!-- Consumed by the upstream mcp-neo4j-cypher server via `maxy-
|
|
2
|
+
<!-- Consumed by the upstream mcp-neo4j-cypher server via `maxy-graph-read_neo4j_cypher`. -->
|
|
3
3
|
<!-- Source of truth for node labels and properties: platform/neo4j/schema.cypher + plugins/memory/references/schema-*.md. -->
|
|
4
4
|
|
|
5
5
|
# Graph interrogation (read-only Cypher cookbook)
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
When a user asks a relational question about their own graph — *"list all my
|
|
8
8
|
people", "how many tasks do I have", "find the person with email X", "what's
|
|
9
9
|
linked to this business", "show me the 20 most recently created nodes" — use
|
|
10
|
-
`maxy-
|
|
10
|
+
`maxy-graph-read_neo4j_cypher` or `maxy-graph-get_neo4j_schema`, not
|
|
11
11
|
`memory-search`. Vector search is for "things like this"; Cypher is for "the
|
|
12
12
|
exact set where".
|
|
13
13
|
|
|
@@ -17,7 +17,7 @@ filter in the query.
|
|
|
17
17
|
|
|
18
18
|
## When the graph tools are absent
|
|
19
19
|
|
|
20
|
-
If neither `maxy-
|
|
20
|
+
If neither `maxy-graph-read_neo4j_cypher` nor `maxy-graph-get_neo4j_schema`
|
|
21
21
|
appears in your tool list, the graph MCP server failed to start on this
|
|
22
22
|
device. Reply once with exactly:
|
|
23
23
|
|
|
@@ -162,7 +162,7 @@ All relationship types:
|
|
|
162
162
|
CALL db.relationshipTypes() YIELD relationshipType RETURN relationshipType ORDER BY relationshipType
|
|
163
163
|
```
|
|
164
164
|
|
|
165
|
-
Or use `maxy-
|
|
165
|
+
Or use `maxy-graph-get_neo4j_schema` for a richer one-shot structural summary.
|
|
166
166
|
|
|
167
167
|
### Fulltext
|
|
168
168
|
|
|
@@ -21,7 +21,7 @@ echo ""
|
|
|
21
21
|
# ------------------------------------------------------------------
|
|
22
22
|
echo "[1/8] Updating system packages and configuring network..."
|
|
23
23
|
sudo apt-get update -qq
|
|
24
|
-
sudo apt-get install -y -qq curl git unzip avahi-daemon avahi-utils
|
|
24
|
+
sudo apt-get install -y -qq curl git unzip avahi-daemon avahi-utils bind9-dnsutils
|
|
25
25
|
|
|
26
26
|
# Set hostname to 'maxy' so device is reachable at maxy.local
|
|
27
27
|
CURRENT_HOSTNAME=$(hostname)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
9
|
+
};
|
|
10
|
+
var __export = (target, all) => {
|
|
11
|
+
for (var name in all)
|
|
12
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from))
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
28
|
+
mod
|
|
29
|
+
));
|
|
30
|
+
|
|
31
|
+
// app/lib/upgrade-progress-parser.ts
|
|
32
|
+
import { existsSync, readFileSync } from "fs";
|
|
33
|
+
var STEP_RE = /\[(\d+)\/(\d+)\]\s+(.+)/;
|
|
34
|
+
var ANSI_RE = /\x1b\[[0-9;?]*[a-zA-Z]/g;
|
|
35
|
+
var stripAnsi = (s) => s.replace(ANSI_RE, "").replace(/\r/g, "").trimEnd();
|
|
36
|
+
var MAX_SUBSTEPS = 20;
|
|
37
|
+
function parseUpgradeProgress(content) {
|
|
38
|
+
const rawLines = content.split("\n");
|
|
39
|
+
let step = 0;
|
|
40
|
+
let total = 0;
|
|
41
|
+
let label = "";
|
|
42
|
+
let markerIdx = -1;
|
|
43
|
+
for (let i = rawLines.length - 1; i >= 0; i--) {
|
|
44
|
+
const match = rawLines[i].match(STEP_RE);
|
|
45
|
+
if (match) {
|
|
46
|
+
step = parseInt(match[1], 10);
|
|
47
|
+
total = parseInt(match[2], 10);
|
|
48
|
+
label = match[3].replace(/\.{3}$/, "").trim();
|
|
49
|
+
markerIdx = i;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const subSteps = markerIdx >= 0 ? rawLines.slice(markerIdx + 1).map(stripAnsi).filter((l) => l.length > 0).slice(-MAX_SUBSTEPS) : [];
|
|
54
|
+
const tail = rawLines.slice(-20).join("\n");
|
|
55
|
+
const finished = tail.includes("Open in your browser:");
|
|
56
|
+
const failed = tail.includes("Setup failed:");
|
|
57
|
+
return { step, total, label, started: true, finished, failed, subSteps };
|
|
58
|
+
}
|
|
59
|
+
function readProgressLog(path) {
|
|
60
|
+
if (!existsSync(path)) {
|
|
61
|
+
return { step: 0, total: 0, label: "", started: false, subSteps: [] };
|
|
62
|
+
}
|
|
63
|
+
let content;
|
|
64
|
+
try {
|
|
65
|
+
content = readFileSync(path, "utf-8");
|
|
66
|
+
} catch {
|
|
67
|
+
return { step: 0, total: 0, label: "", started: false, subSteps: [] };
|
|
68
|
+
}
|
|
69
|
+
return parseUpgradeProgress(content);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
__commonJS,
|
|
74
|
+
__export,
|
|
75
|
+
__toESM,
|
|
76
|
+
readProgressLog
|
|
77
|
+
};
|